package com.cuijq.dubbo.core.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PreDestroy;

@Configuration
@Slf4j
public class NettyServer implements ApplicationRunner {
    @Autowired
    ServerBootstrap server;
    @Autowired
    NioEventLoopGroup boss;
    @Autowired
    NioEventLoopGroup serverWorker;
    private Channel channel;
    @Value("${netty.port:8080}")
    Integer port;
    @Autowired
    NettyServerHandle nettyServerHandle;
    public void start(int port) {
        server.group(boss, serverWorker)
                .channel(NioServerSocketChannel.class);
        server.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) {
                ch.pipeline().addLast("decode", new ObjectDecoder(ClassResolvers.weakCachingConcurrentResolver(
                        this.getClass().getClassLoader())));
                ch.pipeline().addLast("encoder", new ObjectEncoder());
                ch.pipeline().addLast(nettyServerHandle);
            }
        }).option(ChannelOption.SO_BACKLOG, 128)
                .childOption(ChannelOption.SO_KEEPALIVE, true);
        ;
        log.info("{}端口启动成功", port);
        try {
            ChannelFuture f = server.bind(port).sync();
            channel = f.channel();
            channel.closeFuture().addListener((ChannelFutureListener) future -> {
                boss.shutdownGracefully();
                serverWorker.shutdownGracefully();
            });
        } catch (InterruptedException e) {
            log.info("{}端口启动失败", e);
        }
    }

    @Override
    public void run(ApplicationArguments args) {
        start(port);
    }
    @PreDestroy
    public void stop() {
        if (channel != null) {
            channel.close();
        }
    }

    public boolean isRunning() {
        if (channel.isActive()) {
            return true;
        } else {
            return false;
        }
    }

}
